﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Collections;
using System.Threading;
using System.DirectoryServices.AccountManagement;
using hzWeb;

namespace zhWeb
{
    class ADManager
    {
        // code from http://www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C#36

        // Create a New Security Group
        public string CreateGroup(string ouPath, string name)
        {
            string path = "LDAP://CN=" + name + "," + ouPath;
            if (!DirectoryEntry.Exists(path))
            {
                try
                {
                    DirectoryEntry entry = new DirectoryEntry("LDAP://" + ouPath);
                    DirectoryEntry group = entry.Children.Add("CN=" + name, "group");
                    group.Properties["sAmAccountName"].Value = name;                  
                    group.Properties["groupType"].Value = -2147483640;
                    group.CommitChanges();
                    //GroupPrincipal newGroup = gr;
                    //newGroup.GroupScope = GroupScope.Universal;
                    //newGroup.Save();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message.ToString());
                }
            }
            else { Console.WriteLine(path + " already exists"); }

            return path;
        }

        // Delete a group
        public void DeleteGroup(string ouPath, string groupPath)
        {
            groupPath = groupPath.Replace("LDAP://", "");
            ouPath = ouPath.Replace("LDAP://", "");
            string path = "LDAP://" + groupPath;
            if (DirectoryEntry.Exists(path))
            {
                try
                {
                    DirectoryEntry entry = new DirectoryEntry("LDAP://" + ouPath);
                    DirectoryEntry group = new DirectoryEntry("LDAP://" + groupPath);
                    entry.Children.Remove(group);
                    group.CommitChanges();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message.ToString());
                }
            }
            else
            {
                Console.WriteLine(path + " doesn't exist");
            }
        }

        // Add User to Group
        public void AddToGroup(string userDn, string groupDn)
        {
            try
            {
                userDn = userDn.Replace("LDAP://", "");
                groupDn = groupDn.Replace("LDAP://", "");
                // R211.ITFirst.local/CN=Lynctest02
                string[] userDNs = userDn.Split("/".ToArray());
                if(userDNs.Length ==2)
                {
                    userDn = userDNs[1];
                }

                DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
                dirEntry.Properties["member"].Add(userDn);
                dirEntry.CommitChanges();
                dirEntry.Close();
            }
            catch (System.DirectoryServices.DirectoryServicesCOMException Ex)
            {
                Helper.WriteLog(string.Format("Add user {0} to AD group {1}failed by:{2}, :{3} ", userDn, groupDn, Ex.Message , Ex.StackTrace + Ex.InnerException));
            }
        }

        // Remove User from Group
        public void RemoveUserFromGroup(string userDn, string groupDn)
        {
            try
            {
                userDn = userDn.Replace("LDAP://", "");
                groupDn = groupDn.Replace("LDAP://", "");
                string[] userDNs = userDn.Split("/".ToArray());
                if (userDNs.Length == 2)
                {
                    userDn = userDNs[1];
                }

                DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
                dirEntry.Properties["member"].Remove(userDn);
                dirEntry.CommitChanges();
                dirEntry.Close();
            }
            catch (System.DirectoryServices.DirectoryServicesCOMException Ex)
            {
                Helper.WriteLog(string.Format("Remove user {0} from AD group {1} failed by:{2}, :{3} ", userDn, groupDn, Ex.Message, Ex.StackTrace + Ex.InnerException));
            }
        }

        public DirectoryEntry SearchADByAlias(string alias, string domainName)
        {
            DirectorySearcher dssearch = new DirectorySearcher("LDAP://" + domainName);

            dssearch.Filter = "(sAMAccountName=" + alias + ")";
            dssearch.SearchScope = SearchScope.Subtree;
            SearchResult sresult = dssearch.FindOne();
            if (sresult == null)
            {
                DomainCollection domains = System.DirectoryServices.ActiveDirectory.Forest.GetCurrentForest().Domains;
                List<string> domainsName = new List<string>();
                foreach(Domain doamin in domains)
                {
                    domainsName.Add(doamin.GetDirectoryEntry().Path);
                }

                return SearchADByAliasInDomains(alias, domainsName);
                
            }
            else
            {
                DirectoryEntry dsresult = sresult.GetDirectoryEntry();
                return dsresult;
            }
        }

        public DirectoryEntry SearchADByAliasInDomains(string alias, List<string> domainsName)
        {
            foreach (var domainName in domainsName)
            {
                DirectoryEntry entry = new DirectoryEntry(domainName);
                DirectorySearcher dssearch = new DirectorySearcher(entry);

                dssearch.Filter = "(sAMAccountName=" + alias + ")";              
                SearchResult sresult = dssearch.FindOne();
                Helper.WriteLog(string.Format("Search user {0} in domain {1}", alias, domainName));
                if (sresult != null)
                {
                    return sresult.GetDirectoryEntry();
                }

                Helper.WriteLog(string.Format("Can't find user {0} in domain {1}", alias, domainName));
            }

            return null;
        }

        public DirectoryEntry SearchADByAlias(string alias, string domainName, bool waitForADSync)
        {
            SearchResult sresult = null;
            DirectorySearcher dssearch = new DirectorySearcher("LDAP://" + domainName);
            dssearch.SearchScope = SearchScope.Subtree;
            dssearch.Filter = "(sAMAccountName=" + alias + ")";
            int loopNumber = 300; // the time out for AD sync is 5 minutes 
            while (null == sresult && loopNumber > 0)
            {
                sresult = dssearch.FindOne();
                loopNumber--;
                Thread.Sleep(1000);
            }

            if (null == sresult)
            {
                throw new Exception("在域" + domainName + "中找不到帐号为" + alias + "的对象");
            }

            DirectoryEntry dsresult = sresult.GetDirectoryEntry();
            return dsresult;
        }


        private void DemoCode()
        {
            try
            {
                ADManager adManager = new ADManager();

                // Add group to OU 
                // Ou path
                // adManager.CreateGroup("OU=chatroom,DC=ITFirst,DC=com", "chatroom001");

                // Group path: "CN=chatroom001,OU=chatroom,DC=ITFirst,DC=com"
                // User path: CN=Test,OU=ITFirst,DC=ITFirst,DC=com
                // "CN=程成,OU=ITFirst,DC=ITFirst,DC=com"
                // Domain name ITFirst.com

                // Add user to security group
                //var result = adManager.SearchADByAlias("chengcheng", "ITFirst.com");
                //if (result != null)
                //{
                //    Console.WriteLine(result.Path);
                //    adManager.AddToGroup(result.Path, "CN=chatroom001,OU=chatroom,DC=ITFirst,DC=com");
                //}

                // Remove user from group 
                //var result = adManager.SearchADByAlias("chengcheng", "ITFirst.com");
                //if (result != null)
                //{
                //    Console.WriteLine(result.Path);
                //    adManager.RemoveUserFromGroup(result.Path, "CN=chatroom001,OU=chatroom,DC=ITFirst,DC=com");
                //}

                // Remove group 
                // adManager.DeleteGroup("OU=chatroom,DC=ITFirst,DC=com", "CN=chatroom001,OU=chatroom,DC=ITFirst,DC=com");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}
